05. 复杂的状态和动作空间
复杂的状态和动作空间
你可能注意到了,结合后的状态动作空间大小非常大。这样可能会导致你开发的任何智能体策略或值函数模型变得更加复杂。
正如在
tasks/takeoff.py
中所定义的,状态向量有 7 个元素,前 3 个表示飞行器在
(x, y, z)
域内的位置,剩下的 4 个表示方向
四元数
:
class Takeoff(BaseTask):
...
def update(self, timestamp, pose, angular_velocity, linear_acceleration):
# Prepare state vector (pose only; ignore angular_velocity, linear_acceleration)
state = np.array([
pose.position.x, pose.position.y, pose.position.z,
pose.orientation.x, pose.orientation.y, pose.orientation.z, pose.orientation.w])
...
同样,动作向量预计由 6 个元素组成,前 3 个会产生线性推力,剩下 3 个会产生扭矩(旋转力):
action = [force_x, force_y, force_z, torque_x, torque_y, torque_z]
但是,所有这些维度可能与手头的问题不相关。例如,为了成功地起飞,你只需知道飞行器的位置(状态向量的前 3 个元素),可以忽略方向。同样,你只需应用线性推力(同样是动作向量的前 3 个元素),不需要应用扭矩(这样还会防止出现不必要的旋转和歪斜)。
限制状态和动作空间
你可以在智能体代码中选择使用提供的状态向量的子集,并有效地限制在特定动作向量维度里采取的动作。为此,首先指定缩减状态和动作空间的大小,然后用来创建策略参数、神经网络模型,等等。
class MyAgent(BaseAgent):
...
def __init__(self, task):
...
# Constrain state and action spaces
self.state_size = 3 # position only
self.action_size = 3 # force only
print("Original spaces: {}, {}\nConstrained spaces: {}, {}".format(
self.task.observation_space.shape, self.task.action_space.shape,
self.state_size, self.action_size))
...
然后你可以定义两个辅助函数 - 一个用来在使用每个状态向量前预处理向量,另一个用来在返回每个动作向量前后处理向量:
def preprocess_state(self, state):
"""Reduce state vector to relevant dimensions."""
return state[0:3] # position only
def postprocess_action(self, action):
"""Return complete action vector."""
complete_action = np.zeros(self.task.action_space.shape) # shape: (6,)
complete_action[0:3] = action # linear force only
return complete_action
最后,从
step()
中调用这些方法:
def step(self, state, reward, done):
# Reduce state vector
state = preprocess_state(state)
...
# Transform state, choose action, save experience, learn, etc.
...
# Return complete action vector
return postprocess_action(action)
如果你发现你的智能体学习效果不好,或者学习速度不快,请尝试限制状态和/或动作空间。你可以选择不同的维度子集,看看哪个效果最好。